Skip to content

Add support for swift-service-lifecycle#55

Merged
FranzBusch merged 30 commits intoswift-server:mainfrom
aryan-25:service-lifecycle
Feb 25, 2026
Merged

Add support for swift-service-lifecycle#55
FranzBusch merged 30 commits intoswift-server:mainfrom
aryan-25:service-lifecycle

Conversation

@aryan-25
Copy link
Collaborator

@aryan-25 aryan-25 commented Feb 9, 2026

Motivation:

The swift-service-lifecycle library is commonly used for managing service lifetimes. We should adopt swift-service-lifecycle for NIOHTTPServer.

Modifications:

  • Updated the child channel initializers for HTTP/1.1 and Secure Upgrade in NIOHTTPServer to use swift-nio-extra's ServerQuiescingHelper. The ServerQuiescingHelper is added to the channel pipeline, and propagates a ChannelShouldQuiesceEvent upon graceful shutdown being triggered.

    • For HTTP/1.1, the HTTPServerPipelineHandler handler, which is contained in the pipeline, already handles ChannelShouldQuiesceEvent events.

    • For HTTP/2, a NIOHTTP2ServerConnectionManager is added to the pipeline. This connection manager reacts to a ChannelShouldQuiesceEvent and gracefully shuts down HTTP/2 connections.

  • Updated NIOHTTPServer's serve(handler:) to handle graceful shutdown (using swift-service-lifecycle's withTaskCancellationOrGracefulShutdownHandler method).

Result:

Support for swift-service-lifecycle added.

@aryan-25 aryan-25 added the 🆕 semver/minor Adds new public API. label Feb 9, 2026
@gjcairo gjcairo self-requested a review February 10, 2026 15:07
public init(
server: Server,
serverHandler: Handler,
onGracefulShutdown gracefulShutdownHandler: @Sendable @escaping () -> Void = {}
Copy link
Contributor

@FranzBusch FranzBusch Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to let the user customize this? They can setup their own handler by wrapping this service if they wanted to.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I hadn't thought about this. I've removed the onGracefulShutdown argument now.

@tib
Copy link
Collaborator

tib commented Feb 16, 2026

Looks very good—just two small additions, though:

  1. I strongly believe you also need to use #if ServiceLifecycle checks in the Tests/NIOHTTPServerTests/NIOHTTPServer+ServiceLifecycleTests.swift file.

Also, make sure you test all trait combinations:

swift test --parallel --traits ServiceLifecycle
swift test --parallel --enable-all-traits
swift test --disable-default-traits
  1. A dedicated section in the README about the available traits would be helpful, similar to the one we have for swift-configuration.

Thank you for the work. 🙏

Package.swift Outdated
traits: [
.trait(name: "SwiftConfiguration"),
.trait(name: "ServiceLifecycle"),
.default(enabledTraits: ["SwiftConfiguration"]),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice if we could also enable the ServiceLifecycle trait by default.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ServiceLifecycle trait is now no longer needed; NIOHTTPServer depends on swift-service-lifecycle by default.

@aryan-25
Copy link
Collaborator Author

Following from #58, I've removed changes to the abstract server API in this PR and created a PR for those changes in the swift-http-api-proposal repository where the abstract server API now resides.

@aryan-25 aryan-25 linked an issue Feb 19, 2026 that may be closed by this pull request
@aryan-25
Copy link
Collaborator Author

Based on some offline discussions, we won't be making any changes to the abstract HTTPServer API.

All HTTPServer implementations should be handling graceful shutdown directly in the serve method.

Users can use the new ClosureService that will be introduced by swift-server/swift-service-lifecycle#227 in order to use a HTTPServer conformance with ServiceGroup (example).

@aryan-25 aryan-25 marked this pull request as ready for review February 20, 2026 14:12
@aryan-25
Copy link
Collaborator Author

API breakage is expected: a new configuration argument was added.

@aryan-25 aryan-25 requested a review from FranzBusch February 24, 2026 12:17
try await withTaskCancellationOrGracefulShutdownHandler {
try await self._serve(handler: handler)
} onCancelOrGracefulShutdown: {
self.close()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong to me. The behavior of a cancellation and graceful shutdown should be different. On cancellation we should force close all the channels on graceful shutdown we should quiesce

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've did some refactoring in order to get a reference to the underlying server channel in the serve method. It now looks like this:

let serverChannel = try await self.makeServerChannel()

return try await withTaskCancellationHandler {
    try await withGracefulShutdownHandler {
        try await self._serve(serverChannel: serverChannel, handler: handler)
    } onGracefulShutdown: {
        self.beginGracefulShutdown()
    }
} onCancel: {
    // Forcefully close down the server channel
    self.close(serverChannel: serverChannel)
}

Copy link
Contributor

@FranzBusch FranzBusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@FranzBusch FranzBusch merged commit 8270dac into swift-server:main Feb 25, 2026
22 of 26 checks passed
@aryan-25 aryan-25 deleted the service-lifecycle branch February 26, 2026 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Service Lifecycle

3 participants